﻿using System.Collections;
using System.Xml;

namespace XMLParsers.DOM
{
    public class XmlDomParser
    {
        private XmlTextReader _reader;
        private Stack _elements;
        private XmlDomElement _currentElement;
        private XmlDomElement _rootElement;

        public XmlDomParser() 
        {
            _elements = new Stack();
            _currentElement = null;
        }

        public XmlDomElement Parse(XmlTextReader reader)
        {
            XmlDomElement simpleElement = null;
            _reader = reader;
            while (!_reader.EOF)
            {
                _reader.Read();
                switch (_reader.NodeType)
                {
                    case XmlNodeType.Element:
                        simpleElement = new XmlDomElement(_reader.LocalName);
                        _currentElement = simpleElement;
                        if (_elements.Count == 0)
                        {
                            _rootElement = simpleElement;
                            _elements.Push(simpleElement);
                        }
                        else
                        {
                            var parent = (XmlDomElement)_elements.Peek();
                            parent.ChildElements.Add(simpleElement);
                            if (_reader.IsEmptyElement) // ends with "/>"
                            {
                                break;
                            }
                            _elements.Push(simpleElement);
                        }
                        if (_reader.HasAttributes)
                        {
                            while (_reader.MoveToNextAttribute())
                            {
                                _currentElement.SetAttribute(_reader.Name, _reader.Value);
                            }
                        }
                        break;
                    case XmlNodeType.Attribute:
                        if (simpleElement != null) 
                            simpleElement.SetAttribute(_reader.Name, _reader.Value);
                        break;
                    case XmlNodeType.EndElement:
                        _elements.Pop();
                        break;
                    case XmlNodeType.Text:
                        _currentElement.Text = _reader.Value;
                        break;
                    case XmlNodeType.CDATA:
                        _currentElement.Text = _reader.Value;
                        break;
                    default:
                        break;
                }
            }
            return _rootElement;
        }
    }
}
